--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Commit ba22f41cf86a5cc1e85cf9b727507b20413208c2
Parents : 24d79c4
Author : Mark Qvist <mark@unsigned.io>
Date : 2021-05-12T14:02:44+02:00
Focus handling
Changes
4 files changed, 120 insertions(+), 45 deletions(-)
Diff
diff --git a/nomadnet/NomadNetworkApp.py b/nomadnet/NomadNetworkApp.py
index 49bdd84..e38ce26 100644
--- a/nomadnet/NomadNetworkApp.py
+++ b/nomadnet/NomadNetworkApp.py
@@ -106,7 +106,7 @@ class NomadNetworkApp:
self.lxmf_destination = self.message_router.register_delivery_identity(self.identity)
RNS.log("LXMF Router ready to receive on: "+RNS.prettyhexrep(self.lxmf_destination.hash))
- self.ui = nomadnet.ui.spawn(self.uimode)
+ nomadnet.ui.spawn(self.uimode)
def lxmf_delivery(self, message):
diff --git a/nomadnet/ui/TextUI.py b/nomadnet/ui/TextUI.py
index a14b657..246d9bd 100644
--- a/nomadnet/ui/TextUI.py
+++ b/nomadnet/ui/TextUI.py
@@ -33,6 +33,7 @@ class TextUI:
def __init__(self):
self.app = NomadNetworkApp.get_shared_instance()
+ self.app.ui = self
self.loop = None
if importlib.util.find_spec("urwid") != None:
diff --git a/nomadnet/ui/textui/Conversations.py b/nomadnet/ui/textui/Conversations.py
index 921d840..993b398 100644
--- a/nomadnet/ui/textui/Conversations.py
+++ b/nomadnet/ui/textui/Conversations.py
@@ -2,19 +2,50 @@ import RNS
import time
import nomadnet
-class ConversationsDisplayShortcuts():
+import urwid
+
+class ListEntry(urwid.Text):
+ _selectable = True
+
+ signals = ["click"]
+
+ def keypress(self, size, key):
+ """
+ Send 'click' signal on 'activate' command.
+ """
+ if self._command_map[key] != urwid.ACTIVATE:
+ return key
+
+ self._emit('click')
+
+ def mouse_event(self, size, event, button, x, y, focus):
+ """
+ Send 'click' signal on button 1 press.
+ """
+ if button != 1 or not urwid.util.is_mouse_press(event):
+ return False
+
+ self._emit('click')
+ return True
+
+
+class ConversationListDisplayShortcuts():
+ def __init__(self, app):
+ self.app = app
+
+ self.widget = urwid.AttrMap(urwid.Text("Conversation List Display Shortcuts"), "shortcutbar")
+
+class ConversationDisplayShortcuts():
def __init__(self, app):
- import urwid
self.app = app
- self.widget = urwid.AttrMap(urwid.Text("Conversations Display Shortcuts"), "shortcutbar")
+ self.widget = urwid.AttrMap(urwid.Text("[C-s] Send"), "shortcutbar")
class ConversationsDisplay():
list_width = 0.33
cached_conversation_widgets = {}
def __init__(self, app):
- import urwid
from nomadnet.vendor.additional_urwid_widgets import IndicativeListBox
self.app = app
@@ -23,12 +54,21 @@ class ConversationsDisplay():
for conversation in app.conversations():
conversation_list_widgets.append(self.conversation_list_widget(conversation))
+ def disp_list_shortcuts(sender, arg1, arg2):
+ self.shortcuts_display = self.list_shortcuts
+ self.app.ui.main_display.update_active_shortcuts()
+ RNS.log("Modified")
+
walker = urwid.SimpleFocusListWalker(conversation_list_widgets)
- listbox = urwid.LineBox(urwid.Filler(IndicativeListBox(conversation_list_widgets), height=("relative", 100)))
+ ilb = IndicativeListBox(conversation_list_widgets)
+ listbox = urwid.LineBox(urwid.Filler(ilb, height=("relative", 100)))
columns_widget = urwid.Columns([("weight", ConversationsDisplay.list_width, listbox), ("weight", 1-ConversationsDisplay.list_width, self.make_conversation_widget(None))], dividechars=0, focus_column=0, box_columns=[0])
- self.shortcuts_display = ConversationsDisplayShortcuts(self.app)
+ self.list_shortcuts = ConversationListDisplayShortcuts(self.app)
+ self.editor_shortcuts = ConversationDisplayShortcuts(self.app)
+
+ self.shortcuts_display = self.list_shortcuts
self.widget = columns_widget
def display_conversation(self, sender=None, source_hash=None):
@@ -38,7 +78,6 @@ class ConversationsDisplay():
def make_conversation_widget(self, source_hash):
time_format = self.app.time_format
- import urwid
class LXMessageWidget(urwid.WidgetWrap):
def __init__(self, message):
title_string = time.strftime(time_format)
@@ -76,44 +115,26 @@ class ConversationsDisplay():
from nomadnet.vendor.additional_urwid_widgets import IndicativeListBox
messagelist = IndicativeListBox(message_widgets)
+ msg_editor = urwid.Edit(caption="\u270E", edit_text="", multiline=True)
+
widget = urwid.LineBox(
urwid.Frame(
messagelist,
- footer=urwid.AttrMap(urwid.Edit(caption="\u270E", edit_text=""), "msg_editor")
+ footer=urwid.AttrMap(msg_editor, "msg_editor")
)
)
+ def disp_editor_shortcuts(sender, arg1, arg2):
+ self.shortcuts_display = self.editor_shortcuts
+ self.app.ui.main_display.update_active_shortcuts()
+
+ urwid.connect_signal(msg_editor, "change", disp_editor_shortcuts, "modified event")
+
ConversationsDisplay.cached_conversation_widgets[source_hash] = widget
return widget
def conversation_list_widget(self, conversation):
- import urwid
-
- class ListEntry(urwid.Text):
- _selectable = True
-
- signals = ["click"]
-
- def keypress(self, size, key):
- """
- Send 'click' signal on 'activate' command.
- """
- if self._command_map[key] != urwid.ACTIVATE:
- return key
-
- self._emit('click')
-
- def mouse_event(self, size, event, button, x, y, focus):
- """
- Send 'click' signal on button 1 press.
- """
- if button != 1 or not urwid.util.is_mouse_press(event):
- return False
-
- self._emit('click')
- return True
-
#widget = urwid.SelectableIcon(str(conversation), cursor_position=-1)
widget = ListEntry(str(conversation))
urwid.connect_signal(widget, "click", self.display_conversation, conversation)
@@ -121,4 +142,10 @@ class ConversationsDisplay():
def shortcuts(self):
- return self.shortcuts_display
\ No newline at end of file
+ focus_path = self.widget.get_focus_path()
+ if focus_path[0] == 0:
+ return self.list_shortcuts
+ elif focus_path[0] == 1:
+ return self.editor_shortcuts
+ else:
+ return self.list_shortcuts
\ No newline at end of file
diff --git a/nomadnet/ui/textui/Main.py b/nomadnet/ui/textui/Main.py
index 34d99ae..e641877 100644
--- a/nomadnet/ui/textui/Main.py
+++ b/nomadnet/ui/textui/Main.py
@@ -1,13 +1,14 @@
import RNS
+import time
from .Network import *
from .Conversations import *
from .Directory import *
from .Map import *
+import urwid
class SubDisplays():
def __init__(self, app):
- import urwid
self.app = app
self.network_display = NetworkDisplay(self.app)
self.conversations_display = ConversationsDisplay(self.app)
@@ -19,17 +20,65 @@ class SubDisplays():
def active(self):
return self.active_display
+class MenuButton(urwid.Button):
+ button_left = urwid.Text('[')
+ button_right = urwid.Text(']')
+
+class MainFrame(urwid.Frame):
+ FOCUS_CHECK_TIMEOUT = 0.25
+
+ def __init__(self, body, header=None, footer=None, delegate=None):
+ self.delegate = delegate
+ self.current_focus = None
+ super().__init__(body, header, footer)
+
+ def keypress_focus_check(self, deferred=False):
+ current_focus = self.delegate.widget.get_focus_widgets()[-1]
+
+ if deferred:
+ if current_focus != self.current_focus:
+ self.focus_changed()
+ else:
+ def deferred_focus_check(loop, user_data):
+ self.keypress_focus_check(deferred=True)
+ self.delegate.app.ui.loop.set_alarm_in(MainFrame.FOCUS_CHECK_TIMEOUT, deferred_focus_check)
+
+ self.current_focus = current_focus
+
+ def focus_changed(self):
+ current_focus = self.delegate.widget.get_focus_widgets()[-1]
+ current_focus_path = self.delegate.widget.get_focus_path()
+ RNS.log("Focus changed to: "+str(current_focus_path))
+
+ if len(current_focus_path) > 1:
+ if current_focus_path[0] == "body":
+ self.delegate.update_active_shortcuts()
+
+ def mouse_event(self, size, event, button, col, row, focus):
+ current_focus = self.delegate.widget.get_focus_widgets()[-1]
+ if current_focus != self.current_focus:
+ self.focus_changed()
+
+ self.current_focus = current_focus
+ return super(MainFrame, self).mouse_event(size, event, button, col, row, focus)
+
+ def keypress(self, size, key):
+ self.keypress_focus_check()
+
+ if key == "ctrl q":
+ raise urwid.ExitMainLoop
+
+ return super(MainFrame, self).keypress(size, key)
class MainDisplay():
def __init__(self, ui, app):
- import urwid
self.ui = ui
self.app = app
self.menu_display = MenuDisplay(self.app, self)
self.sub_displays = SubDisplays(self.app)
- self.frame = urwid.Frame(self.sub_displays.active().widget, header=self.menu_display.widget, footer=self.sub_displays.active().shortcuts().widget)
+ self.frame = MainFrame(self.sub_displays.active().widget, header=self.menu_display.widget, footer=self.sub_displays.active().shortcuts().widget, delegate=self)
self.widget = self.frame
def show_network(self, user_data):
@@ -50,17 +99,15 @@ class MainDisplay():
def update_active_sub_display(self):
self.frame.contents["body"] = (self.sub_displays.active().widget, None)
+ self.update_active_shortcuts()
+
+ def update_active_shortcuts(self):
self.frame.contents["footer"] = (self.sub_displays.active().shortcuts().widget, None)
+
class MenuDisplay():
def __init__(self, app, handler):
- import urwid
-
- class MenuButton(urwid.Button):
- button_left = urwid.Text('[')
- button_right = urwid.Text(']')
-
self.app = app
menu_text = ("pack", urwid.Text(" \U00002638"))
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────